package org.liujing.jsw.client.ui;

import java.util.*;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.DOM;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.*;
import com.google.gwt.core.client.GWT;

public class ContainerImpl extends ComponentImpl implements HasWidgets{

	LayoutManager layoutMgr;
	private java.util.List<Widget> component = new java.util.ArrayList<Widget>();
	
    private boolean validateRoot = false;
    
	public ContainerImpl(JComponent w){
		super(w);
	}

	  public void doAttachChildren() {
	  	  for(Widget c : component){
	  	  	  ((JComponent)c).onAttach();
	  	  }
	  }

	  public void doDetachChildren() {
		for(Widget c : component){
	  	  	  ((JComponent)c).onDetach();
	  	 }
	  }
	  
	 public void onLoad(){
		if(! (getParent() instanceof JComponent)){
			validateRoot = true;
		}
	}
	
	public LayoutManager getLayout() {
		return layoutMgr;
    }

    
    public void setLayout(LayoutManager mgr) {
		layoutMgr = mgr;
		if (valid) {
			invalidate();
		}
    }

	public JComponent add(JComponent comp) {
        addImpl(comp, null, -1);
        return comp;
    }
    
    public void add(Widget w){
    	if(! (w instanceof JComponent))
    		throw new IllegalArgumentException("Only support JComponent as child widget");
    	add((JComponent)w);
    }
    
    public void clear(){
    	//todo
    }

    public Iterator<Widget> iterator(){
    	return (Iterator<Widget>)component.iterator();
    }

    public boolean remove(Widget w){
    	//todo
    	return true;
    }
    
    public JComponent add(String name, JComponent comp) {
    	addImpl(comp, name, -1);
	return comp;
    }
    
    public JComponent add(JComponent comp, int index) {
    	addImpl(comp, null, index);
	return comp;
    }
    
    public void add(JComponent comp, Object constraints) {
    	addImpl(comp, constraints, -1);
    }

    public void add(JComponent comp, Object constraints, int index) {
       addImpl(comp, constraints, index);
    }
    
    public void remove(JComponent comp) {
    	comp.removeNotify();
    	//todo
    }
    
    
    protected void addImpl(JComponent comp, Object constraints, int index) {

    	if (index > component.size() || (index < 0 && index != -1)) {
		throw new IllegalArgumentException(
			  "illegal component position");
	    }
	    //comp.removeFromParent();
    	if (comp.getParent() != null) {
    		comp.getParent().remove(comp);
            if (index > component.size()) {
                throw new IllegalArgumentException("illegal component position");
            }
        }

        //index == -1 means add to the end.
        if (index == -1) {
                component.add((Widget)comp);
	    } else {
                component.add(index, (Widget)comp);
	    }
	    
    	if (valid) {
    		invalidate();
	    }
	    if(comp.isDomElementSet())
	    	gwtWidget.getContentElement().appendChild(comp.getDomElement());
	    
	    comp.setParent((Container)gwtWidget);
		comp.addNotify();
		if(comp.isDomElementSet()){
			Style style = comp.getDomElement().getStyle();
			style.setPosition(Style.Position.ABSOLUTE);
			style.setOverflow(Style.Overflow.HIDDEN);
		}
	    if (layoutMgr != null) {
			if (layoutMgr instanceof LayoutManager2) {
				((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
			} else if (constraints instanceof String) {
				layoutMgr.addLayoutComponent((String)constraints, comp);
			}
	    }
    }
    
    public JComponent getComponent(int n) {
	
        if ((n < 0) || (n >= component.size())) {
        	throw new ArrayIndexOutOfBoundsException("No such child: " + n);
	    }
        return (JComponent)component.get(n);
    }
    
    
	public boolean isValidateRoot() {
        return validateRoot;
    }
    
    public void invalidate() {
        LayoutManager layoutMgr = this.layoutMgr;
	if (layoutMgr instanceof LayoutManager2) {
	    LayoutManager2 lm = (LayoutManager2) layoutMgr;
	    lm.invalidateLayout((Container)gwtWidget);
	}
	super.invalidate();
    }
    
    public void validate() {
    	if (!valid) {
    		doLayout();
            for (int i = 0; i < component.size(); i++) {
                JComponent comp = (JComponent)component.get(i);
                if (   (comp instanceof Container) ) {
                    ((Container)comp).validate();
                }
            }
		    valid = true;
		}
    }
    
    public void doLayout() {
    	GWT.log("Container.doLayout() " + gwtWidget.getClass().getName());
    	LayoutManager layoutMgr = this.layoutMgr;
		if (layoutMgr != null) {
			layoutMgr.layoutContainer((Container)gwtWidget);
		}
    }
    
    public int getComponentCount() {
    	return component.size();
    }
    
    @Override
    @Deprecated
    public Dimension preferredSize() {
			Dimension dim = prefSize;
			if (dim == null || !(isPreferredSizeSet() || isValid())) {
			
			prefSize = (layoutMgr != null) ?
				layoutMgr.preferredLayoutSize((Container)gwtWidget) :
				super.preferredSize();
					dim = prefSize;
		}
        if (dim != null){
            return new Dimension(dim);
        }
        else{
            return dim;
        }
    
    }

    @Override
    @Deprecated
    public Dimension minimumSize() {
    	Dimension dim = minSize;
    	if (dim == null || !(isMinimumSizeSet() || isValid())) {
		minSize = (layoutMgr != null) ?
			layoutMgr.minimumLayoutSize((Container)gwtWidget) :
			super.minimumSize();
				dim = minSize;
		}
		if (dim != null){
			return new Dimension(dim);
		}
		else{
			return dim;
		}
    }

    @Override
    public Dimension getMaximumSize() {
    	if (isMaximumSizeSet()) {
            return new Dimension(maxSize);
        }
    	Dimension size = null;
        if (ui != null) {
            size = ui.getMaximumSize(gwtWidget);
        }
        if(size != null)
        	return size;
    	Dimension dim = maxSize;
    	if (dim == null || !(isMaximumSizeSet() || isValid())) {
	    
              if (layoutMgr instanceof LayoutManager2) {
                   LayoutManager2 lm = (LayoutManager2) layoutMgr;
                   maxSize = lm.maximumLayoutSize((Container)gwtWidget);
              } else {
                   maxSize = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
              }
              dim = maxSize;
        }
        if (dim != null){
            return new Dimension(dim);
        }
        else{
            return dim;
        }
    }

    public float getAlignmentX() {
	float xAlign;
	if (layoutMgr instanceof LayoutManager2) {
	    //synchronized (getTreeLock()) {
		LayoutManager2 lm = (LayoutManager2) layoutMgr;
		xAlign = lm.getLayoutAlignmentX((Container)gwtWidget);
	   // }
	} else {
	    xAlign = super.getAlignmentX();
	}
	return xAlign;
    }


    public float getAlignmentY() {
		float yAlign;
		if (layoutMgr instanceof LayoutManager2) {
			//synchronized (getTreeLock()) {
			LayoutManager2 lm = (LayoutManager2) layoutMgr;
			yAlign = lm.getLayoutAlignmentY((Container)gwtWidget);
			//}
		} else {
			yAlign = super.getAlignmentY();
		}
		return yAlign;
    }
    
}
